/* IF2030 - Algorirma dan Struktur Data */
/* Kelas/Kelompok/Tahun  : 03/09/2011 */
/* Tanggal   : 2 Desember 2011 */
/* File      : list.h */
/* Deskripsi : Header dari ADT List Pengguna dan Pertemanannya */

#ifndef TBList_h
#define TBList_h
#include <stdio.h>
#include <stdlib.h>
#include "../boolean/boolean.h"
#include "../string/string.h"
#include "../tanggal/tanggal.h"



/* ************************ADT List Berkait****************** */
//Struktur data list berkait dengan representasi tabel

/* DEKLARASI KONSTANTA */
#define Nil NULL

/* DEKLARASI TIPE BENTUKAN */
typedef struct tPerson* addressPerson;
typedef struct tFriend* addressFriend;

typedef struct {
    addressPerson First;
    addressPerson Last;
} ListPerson;

typedef struct {
    addressFriend First;
    addressFriend Last;
} ListFriend;

typedef struct {
    string Email;
    string Nama;
    date Lahir;
    string Kota;
    string Universitas;
    string Sma;
} Data;

typedef struct tPerson {
    ListFriend Friend;
    Data DataUser;
    addressPerson Next;
} Person;

typedef struct tFriend {
    addressPerson Person;
    addressFriend Next;
} Friend;




/* DEKLARASI SELEKTOR */
#define First(L) (L).First
#define Last(L) (L).Last
#define NextPerson(P) (*P).Next
#define NextFriend(P) (*P).Next
#define Info(P) (*P)
#define Friend(P) (*P).Friend
#define FriendPerson(Person) (Person).Friend
#define Data(Person) (Person).DataUser
#define Email(D) (D).Email
#define Nama(D) (D).Nama
#define Lahir(D) (D).Lahir
#define Kota(D) (D).Kota
#define Universitas(D) (D).Universitas
#define Sma(D) (D).Sma

// *********** Protoype Primitif Pemrosesan List ***********

//procedure AlokasiPerson (output P : addressPerson)
//{ Mengambil memori dari komputer sebagai memori siap pakai untuk elemen }
//{ I.S. Sembarang. }
//{ F.S. P adalah pointer yang sudah dialokasikan alamatnya
//menghasilkan P=Nil apabila memori sudah penuh dan tulis pesan "Alokasi Memori gagal" }
void AlokasiPerson(addressPerson *P);

//procedure AlokasiFriend (output P : addressFriend)
//{ Mengambil memori dari komputer sebagai memori siap pakai untuk elemen }
//{ I.S. Sembarang. }
//{ F.S. P adalah pointer yang sudah dialokasikan alamatnya
//menghasilkan P=Nil apabila memori sudah penuh dan tulis pesan "Alokasi Memori gagal" }
void AlokasiFriend(addressFriend *P);

// procedure DealokasiPerson (input P : addressPerson)
// { Mengembalikan memori elemen P ke sistem }
// { I.S. P tidak Nil. }
// { F.S. Memori P dikembalikan ke sistem }
void DealokasiPerson(addressPerson *P);

// procedure DealokasiFriend (input P : addressFriend)
// { Mengembalikan memori elemen P ke sistem }
// { I.S. P tidak Nil. }
// { F.S. Memori P dikembalikan ke sistem }
void DealokasiFriend(addressFriend *P);

// ***************** TEST LIST KOSONG *****************

//function PersonEmpty (L : ListPerson) -> boolean
//{ Mengirim true jika ListPerson kosong }
boolean PersonEmpty(ListPerson L);

//function FriendEmpty (L : ListFriend) -> boolean
//{ Mengirim true jika ListFriend kosong }
boolean FriendEmpty(ListFriend L);

// ***************** PEMBUATAN LIST KOSONG *****************

//procedure CreateListPerson (output L : ListPerson)
//{ Membentuk ListPerson baru }
//{ I.S. sembarang }
//{ F.S. Terbentuk ListPerson kosong }
void CreateListPerson(ListPerson *L);

//procedure CreateListFriend (output L : ListFriend)
//{ Membentuk ListFriend baru }
//{ I.S. sembarang }
//{ F.S. Terbentuk ListFriend kosong }
void CreateListFriend(ListFriend *L);

// ***************** PENCARIAN *****************

//function EmailSearch(input/output LP : ListPerson, input X : string) -> addressPerson
//{ Menghasilkan addressPerson dari user yang memiliki ID email X }
addressPerson EmailSearch(ListPerson *LP, string X);

// ***************** PENYALINAN DATA *****************

//procedure SalinData(output destination : Person, input source : Person)
//{ Menyalin seluruh data user dari source ke destination }
//{ I.S. Data destination kosong }
//{ F.S. Data destination = Data source }
void SalinData(Person *destination, Person source);

// ***************** PENAMBAHAN ELEMEN *****************

//procedure InsertPersonSort(input/output L : ListPerson, input X : Person)
//{ Menambahkan X sebagai elemen ListPerson L terurut ascending berdasarkan nama }
//{ I.S. L bisa kosong }
//{ F.S. X dialokasikan dan masuk sebagai elemen L terurut ascending berdasar nama }
void InsertPersonSort(ListPerson *LP, Person X);

//procedure InsertFriend(input/output L : ListFriend, input X : addressPerson)
//{ Menambahkan X sebagai elemen terakhir ListPerson L }
//{ I.S. L bisa kosong }
//{ F.S. X dialokasikan dan masuk sebagai elemen terakhir L }
void InsertFriend(ListFriend *L, addressPerson X);

// ***************** PENCETAKAN ELEMEN *****************

//procedure PrintTableHeader
//{ Mencetak header tampilan tabel ListPerson sebagai baris informasi isi tabel }
//{ I.S. Sembarang }
//{ F.S. Baris pertama tampilan tabel yang berisi informasi isi tabel tercetak }
void PrintTableHeader ();

//procedure PrintTableFooter
//{ Mencetak footer tampilan tabel ListPerson sebagai penutup tabel }
//{ I.S. Sembarang }
//{ F.S. Baris terakhir tampilan tabel sebagai penutup tabel tercetak }
void PrintTableFooter ();

//procedure PrintPerson(input P : addressPerson)
//{ Mencetak isi data user dari user yang beralamatkan P }
//{ I.S. Sembarang }
//{ F.S. Data user beralamatkan P tercetak }
void PrintPerson(addressPerson P);

//procedure PrintPersonMasking(input P : addressPerson, input FirstFriend : boolean)
//{ Mencetak isi data user dari user yang beralamatkan P dan menyamarkan tanggal lahir bila belum berteman dengannya }
//{ I.S. Sembarang }
//{ F.S. Data user beralamatkan P tercetak, jika user beralamatkan P belum
//berteman, maka field tanggal lahir dicetak XX-XX-XXXX }
void PrintPersonMasking(addressPerson P, boolean FirstFriend);

//procedure PrintSamePerson(input LP : ListPerson, input CUser : addressPerson, input Pilihan : string)
//{ Mencetak data user yang merupakan 1st, 2nd, dan 3rd friend dari CUser dan memiliki data SMA, universitas,
//atau kota asal yang sama tergantung masukan}
//{ I.S. LP tidak kosong }
//{ F.S. Jika Pilihan = school maka ditampilkan data user yang merupakan 1st, 2nd, atau 3rd friend dengann CUser
//yang memiliki SMA atau universitas yang sama dengan CUser, jika Pilihan = hometown, maka ditampilkan
//yang memiliki kota asal yang sama dengan CUser }
void PrintSamePerson(ListPerson LP, addressPerson CUser, string Pilihan);

// ***************** PENGHAPUSAN ELEMEN *****************

//procedure DelFirstFriend(input/output LF : ListFriend, output P : addressFriend)
//{ Menghapus elemen pertama dari ListFriend LF dan mengeluarkan alamat yang dihapus}
//{ I.S. LF tidak kosong }
//{ F.S. Elemen pertama list dihapus, nilai address disimpan di P, P belum didealokasi }
void DelFirstFriend(ListFriend *LF, addressFriend *P);

//procedure DelFriend(input/output LF : ListFriend, input/output P : addressFriend)
//{ Menghapus elemen beralamat P dari ListFriend LF dan mengeluarkan alamat yang dihapus }
//{ I.S. LF tidak kosong }
//{ F.S. Elemen beralamat P dari list dihapus, nilai address disimpan di P,
//P didealokasi}
void DelFriend(ListFriend *LF, addressFriend *P);

//procedure DelLastFriend(input/output LF : ListFriend, output P : addressFriend)
//{ Menghapus elemen terakhir dari ListFriend LF dan mengeluarkan alamat yang dihapus}
//{ I.S. LF tidak kosong }
//{ F.S. Elemen terakhir list dihapus, nilai address disimpan di P, P belum didealokasi }
void DelLastFriend(ListFriend *LF, addressFriend *P);

//procedure DelAllFriend(input/output LF : ListFriend)
//{ Menghapus semua elemen dari ListFriend LF dan mendealokasikan semua memori elemen }
//{ I.S. LF tidak kosong }
//{ F.S. Semua Elemen dari list dihapus, semua memori didealokasi }
void DelAllFriend(ListFriend *LF);

//procedure DelFirstPerson(input/output LP : ListFriend, output P : addressFriend)
//{ Menghapus elemen pertama dari ListPerson LP dan mengeluarkan alamat yang dihapus}
//{ I.S. LP tidak kosong }
//{ F.S. Elemen pertama list dihapus, nilai address disimpan di P, P belum didealokasi }
void DelFirstPerson(ListPerson *LP, addressPerson *P);

//procedure DelLastPerson(input/output LP : ListFriend, output P : addressFriend)
//{ Menghapus elemen terakhir dari ListPerson LP dan mengeluarkan alamat yang dihapus}
//{ I.S. LP tidak kosong }
//{ F.S. Elemen terakhir list dihapus, nilai address disimpan di P, P belum didealokasi }
void DelLastPerson(ListPerson *LP, addressPerson *P);

//procedure DelPerson(input/output LP : ListFriend, input/output P : addressFriend)
//{ Menghapus elemen beralamat P dari ListPerson LP dan mengeluarkan alamat yang dihapus}
//{ I.S. LP tidak kosong }
//{ F.S. Elemen beralamat P list dihapus, nilai address disimpan di P, P belum didealokasi }
void DelPerson(ListPerson *LP, addressPerson *P);

//procedure DelAllPerson(input/output LP : ListFriend)
//{ Menghapus semua elemen dari ListPerson LP dan mendealokasikan memori yang dipakai}
//{ I.S. LP tidak kosong }
//{ F.S. Semua elemen di list dihapus, semua memori yang dipakai didealokasi }
void DelAllPerson(ListPerson *LP);

// ***************** PENGHITUNGAN JUMLAH ELEMEN *****************

// function NbPerson(input LP : ListPerson) -> integer
//{ Menghasilkan jumlah elemen pada ListPerson LP }
int NbPerson(ListPerson LP);

// ***************** SORTING *****************

//procedure SortPerson(input/output TabP : addressPerson*, input NTab : integer, input Pilihan : string, input SortMode : string)
//{ Melakukan proses sorting terhadap array TabP yang berisi addressPerson sesuai pilihan dari masukan }
//{ I.S. TabP terdefinisi dan berisi addressPerson, NTab bernilai jumlah elemen TabP }
//{ F.S. TabP terurut berdasar input Pilihan dan SortMode, jika SortMode = asc maka akan diurut meningkat sedangkan jika
//SortMode = desc maka akan diurut menurun }
void SortPerson(addressPerson *TabP, int NTab, string Pilihan, string SortMode);

//procedure PrintPersonSort(input/output LP : ListPerson, input Pilihan : string, input SortMode : string)
//{ Melakukan print terhadap ListPerson dengan mengurutkannya sesuai input terlebih dahulu }
//{ I.S. LP terdefinisi dan tidak kosong }
//{ F.S. LP dicetak terurut berdasar input Pilihan dan SortMode, jika SortMode = asc maka akan diurut meningkat sedangkan jika
//SortMode = desc maka akan diurut menurun }
void PrintPersonSort(ListPerson *LP, string Pilihan, boolean AscSortMode);

// ***************** PENGECEKAN TINGKAT PERTEMANAN *****************

// function IsFirstFriend(input user : addressPerson, input userfriend : addressPerson) -> boolean
//{ Menghasilkan true bila user berteman dengan userfriend }
boolean IsFirstFriend(addressPerson user, addressPerson userfriend);

// function IsSecondFriend(input user : addressPerson, input userfriend : addressPerson) -> boolean
//{ Menghasilkan true bila userfriend merupakan second friend dari user }
boolean IsSecondFriend(addressPerson user, addressPerson userfriend);

// function IsThirdFriend(input user : addressPerson, input userfriend : addressPerson) -> boolean
//{ Menghasilkan true bila userfriend merupakan third friend dari user }
boolean IsThirdFriend(addressPerson user, addressPerson userfriend);

// function WhichFriend(input user : addressPerson, input userfriend : addressPerson) -> integer
//{ Menghasilkan derajat pertemanan paling rendah dari userfriend terhadap user }
int WhichFriend(addressPerson user, addressPerson userfriend);

//procedure QuickSortTablePerson(input/output TabP : addressPerson*, input first : integer, input last : integer input Pilihan : string)
//{ Melakukan proses sorting terhadap array TabP yang berisi addressPerson sesuai pilihan dari masukan }
//{ I.S. TabP terdefinisi dan berisi addressPerson, first bernilai awal elemen TabP ygb akan diuet dan last adalah elemen terakhirnya }
//{ F.S. TabP terurut menaik berdasar input Pilihan }
void QuickSortTablePerson(addressPerson *TabP, int first, int last, string pilihan);

/* Mencetak first friend yang berulang tahun dalam rentang today dalam beberapa Hari hari kedepan */
/* I.S: LP, email, hari terdefinisi. today adalah date yang valid */
/* F.S: Tercetak pada layar, first friend yang berulangtahun dalam Hari hari kedepan semenjak today */
void PrintBirthday (ListPerson *LP, string email, date today, int Hari);
#endif
